using System;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace TXLooker.Hooks
{
    internal class Win32
    {
        public const int CWP_ALL = 0;
        public const int CWP_SKIPINVISIBLE = 1;
        public const int CWP_SKIPTRANSPARENT = 4;
        public const int HC_ACTION = 0;
        public const uint MOUSEEVENTF_ABSOLUTE = 0x8000;
        public const uint MOUSEEVENTF_LEFTDOWN = 2;
        public const uint MOUSEEVENTF_LEFTUP = 4;
        public const uint MOUSEEVENTF_MIDDLEDOWN = 0x20;
        public const uint MOUSEEVENTF_MIDDLEUP = 0x40;
        public const uint MOUSEEVENTF_MOVE = 1;
        public const uint MOUSEEVENTF_RIGHTDOWN = 8;
        public const uint MOUSEEVENTF_RIGHTUP = 0x10;
        public const uint MOUSEEVENTF_VIRTUALDESK = 0x4000;
        public const uint MOUSEEVENTF_WHEEL = 0x800;
        public const uint MOUSEEVENTF_XDOWN = 0x80;
        public const uint MOUSEEVENTF_XUP = 0x100;
        public const int WH_KEYBOARD = 2;
        public const int WH_KEYBOARD_LL = 13;
        public const int WH_MOUSE = 7;
        public const int WH_MOUSE_LL = 14;
        public const int WHEEL_DELTA = 120;
        public const int WM_CHANGECBCHAIN = 0x30d;
        public const int WM_DRAWCLIPBOARD = 0x308;
        public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int WM_LBUTTONDBLCLK = 0x203;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int WM_MBUTTONDBLCLK = 0x209;
        public const int WM_MBUTTONDOWN = 0x207;
        public const int WM_MBUTTONUP = 520;
        public const int WM_MOUSEHWHEEL = 0x20e;
        public const int WM_MOUSEMOVE = 0x200;
        public const int WM_MOUSEWHEEL = 0x20a;
        public const int WM_NCXBUTTONDBLCLK = 0xad;
        public const int WM_NCXBUTTONDOWN = 0xab;
        public const int WM_NCXBUTTONUP = 0xac;
        public const int WM_RBUTTONDBLCLK = 0x206;
        public const int WM_RBUTTONDOWN = 0x204;
        public const int WM_RBUTTONUP = 0x205;
        public const int WM_SYSKEYDOWN = 260;
        public const int WM_SYSKEYUP = 0x105;
        public const int WM_XBUTTONDBLCLK = 0x20d;
        public const int WM_XBUTTONDOWN = 0x20b;
        public const int WM_XBUTTONUP = 0x20c;
        public const int WS_ACTIVECAPTION = 1;
        public const uint XBUTTON1 = 1;
        public const uint XBUTTON2 = 2;

        [DllImport("user32", SetLastError = true)]
        public static extern int CallNextHookEx(IntPtr hhk, int nCode, uint wParam, ref KBDLLHOOKSTRUCT lParam);
        [DllImport("user32", SetLastError = true)]
        public static extern int CallNextHookEx(IntPtr hhk, int nCode, uint wParam, ref MSLLHOOKSTRUCT lParam);
        [DllImport("user32", SetLastError = true)]
        public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);
        [DllImport("user32", SetLastError = true)]
        public static extern uint SendInput(uint cInputs, ref MSINPUT pInputs, int cbSize);
        [DllImport("user32", SetLastError = true)]
        public static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);
        [DllImport("user32", SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx(int idHook, WKCallBack lpfn, IntPtr hMod, uint dwThreadId);
        [DllImport("user32", SetLastError = true)]
        public static extern IntPtr SetWindowsHookEx(int idHook, WMCallBack lpfn, IntPtr hMod, uint dwThreadId);
        [DllImport("user32", SetLastError = true)]
        public static extern bool UnhookWindowsHookEx(IntPtr hook);
        [DllImport("user32", SetLastError = true)]
        public static extern IntPtr WindowFromPoint(Point pt);

        [StructLayout(LayoutKind.Sequential)]
        public struct KBDLLHOOKSTRUCT
        {
            public uint vkCode;
            public uint scanCode;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MOUSEINPUT
        {
            public int dx;
            public int dy;
            public int mouseData;
            public uint dwFlags;
            public uint time;
            public IntPtr dwExtraInfo;
            public int GetSize()
            {
                return (20 + IntPtr.Size);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MSINPUT
        {
            public int dwType;
            public Win32.MOUSEINPUT xi;
            public int GetSize()
            {
                return (4 + this.xi.GetSize());
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        internal struct MSLLHOOKSTRUCT
        {
            public Point pt;
            public int mouseData;
            public uint flags;
            public uint time;
            public IntPtr dwExtraInfo;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct Rect
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;
            public bool IsEmpty
            {
                [DebuggerHidden]
                get
                {
                    return (((this.Right - this.Left) < 1) | ((this.Bottom - this.Top) < 1));
                }
            }
            [DebuggerHidden]
            public Rectangle ToRectangle()
            {
                return new Rectangle(this.Left, this.Top, this.Right - this.Left, this.Bottom - this.Top);
            }

            [DebuggerHidden]
            public void Inflate(int width, int height)
            {
                if (!this.IsEmpty)
                {
                    this.Left -= width;
                    this.Right += width;
                    this.Top -= height;
                    this.Bottom += height;
                }
            }

            public void Copy(Win32.Rect rect)
            {
                this.Left = rect.Left;
                this.Right = rect.Right;
                this.Top = rect.Top;
                this.Bottom = rect.Bottom;
            }
        }

        public delegate int WKCallBack(int nCode, uint wParam, ref Win32.KBDLLHOOKSTRUCT lParam);

        public delegate int WMCallBack(int nCode, uint wParam, ref Win32.MSLLHOOKSTRUCT lParam);
    }
}
